using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace Sec_scan漏洞扫描系统.Sec_Service
{
    /// <summary>
    /// 漏洞扫描服务
    /// </summary>
    public class Sec_LoopScan_Service
    {
        private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
        {
            return true;
        }
        /// <summary>
        /// 执行单纯的漏洞扫描
        /// </summary>
        /// <param name="loop"></param>
        /// <returns></returns>
        public static string LoopScanInfo(string loop)
        {
            //初始化公共接口
            Sec_Api.Sec_LoopScan_Service_Api.Id = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Loopname = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Looppayload = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Loopkeyword = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Loopaddr = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Looptype = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Looplevel = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Loopnumber = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Cnvd = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Cnnvd = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Cve = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Revise = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Accuracy = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.Addtime = new StringBuilder();
            Sec_Api.Sec_LoopScan_Service_Api.UrlBase = new StringBuilder();
            string url = Sec_Api.Sec_LoopScan_Service_Api.Url.ToString();//获取漏洞扫描地址
            string loops = Sec_Api.Sec_AllAPI.Sqlclient(Sec_Api.Sec_LoopScan_Service_Api.P1);//链接漏洞数据库
            SQLiteConnection connection = new SQLiteConnection(loops);
            try
            {
                connection.Open();
                if(connection.State == System.Data.ConnectionState.Open)
                {
                    //数据库能打开的情况下
                    string sql = Sec_Api.Sec_AllAPI.LoopInfo(Sec_Api.Sec_LoopScan_Service_Api.P1);//查询漏洞数据库
                    SQLiteCommand command = new SQLiteCommand(sql, connection);
                    using(SQLiteDataReader dr = command.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
                    {
                        while (dr.Read())
                        {
                            //获取数据
                            string id = dr["ID"].ToString();//主键
                            string loopname = dr["sec_loopname"].ToString();//漏洞名称
                            string looppayload = dr["sec_looppayload"].ToString();//有效载荷
                            string loopkeyword = dr["sec_loopkeyword"].ToString();//关键特征
                            //漏洞解密 先进行解密 在进行解码
                            string key_1 = Sec_Api.Sec_DesThreDesApi.DesKeyInfo(Sec_Api.Sec_DesThreDesApi.D1);//密文一
                            string key_2 = Sec_Api.Sec_DesThreDesApi.DeskeyInfoOne(Sec_Api.Sec_DesThreDesApi.D1);//密文二
                            string key_3 = Sec_Api.Sec_DesThreDesApi.DeskeyInfoTwo(Sec_Api.Sec_DesThreDesApi.D1);//密文三
                            string payloads = Sec_Config.Sec_DesThreDes.Decrypt(looppayload, key_1, key_2, key_3);//对有效载荷进行加密
                            string keys = Sec_Config.Sec_DesThreDes.Decrypt(loopkeyword, key_1, key_2, key_3);//对有效载荷进行加密
                            //漏洞解码
                            string base1 = Sec_Config.Sec_Base64Code.Gobase64(payloads);//有效载荷
                            string base2 = Sec_Config.Sec_Base64Code.Gobase64(keys);//关键特征

                            string loopaddr = dr["sec_loopaddr"].ToString();//漏洞地址
                            string looptype = dr["sec_looptype"].ToString();//漏洞类型
                            string looplevel = dr["sec_looplevel"].ToString();//漏洞等级
                            string loopnumber = dr["sec_loopnumber"].ToString();//漏洞编号
                            string cnvd = dr["sec_cnvd"].ToString();//CNVD编号
                            string cnnvd = dr["sec_cnnvd"].ToString();//CNNVD编号
                            string cve = dr["sec_cve"].ToString();//CVE编号
                            string revise = dr["sec_revise"].ToString();//修复建议
                            string accuracy = dr["sec_accuracy"].ToString();//漏洞准确率
                            string addtime = dr["sec_addtime"].ToString();//添加时间
                            try
                            {
                                ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate;
                                HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(url + base1);//base1为有效载荷
                                httpReq.Method = "GET";//获取请求方式
                                httpReq.Accept = "*/*";
                                httpReq.ServicePoint.Expect100Continue = false;//加快载入速度
                                httpReq.ServicePoint.UseNagleAlgorithm = false;//禁止nagle算法加快载入速度
                                httpReq.AllowWriteStreamBuffering = false;//禁止缓冲加快载入速度
                                //下面这行可能会造成解析的代码乱码
                                //httpReq.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");//定义gzip压缩页面支持
                                httpReq.ContentType = "application/x-www-form-urlencoded";//定义文档类型及编码
                                httpReq.AllowAutoRedirect = false;//禁止自动跳转
                                httpReq.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36";
                                //httpReq.Timeout = 2000;//请求超时
                                httpReq.KeepAlive = true;//启用长连接
                                httpReq.ServicePoint.ConnectionLimit = int.MaxValue;//定义最大连接数
                                HttpWebResponse response = (HttpWebResponse)httpReq.GetResponse();
                                Stream receiveStream = response.GetResponseStream();
                                StreamReader readStream = new StreamReader(receiveStream, Encoding.GetEncoding("UTF-8"));
                                string html = readStream.ReadToEnd();
                                string sload = html;//获取源代码
                                string patten = base2;//获取网页中的特殊字符 也是关键能不能判断到是否存在漏洞
                                for (int i = 0; i < 1; i++)
                                {
                                    if (System.Text.RegularExpressions.Regex.IsMatch(sload, patten))
                                    {
                                        if (html.Length >= 1)
                                        {
                                            //未存在规则内
                                            Console.WriteLine("未存在规则内的情况下，不进行报错：" + DateTime.Now);
                                        }
                                        else
                                        {
                                            //存在规则内，针对存在规则内的需要对其相关信息进行输出
                                            Sec_Api.Sec_LoopScan_Service_Api.Id.Append(id + "\r\n");//漏洞主键编号
                                            Sec_Api.Sec_LoopScan_Service_Api.Loopname.Append(loopname + "\r\n");//传出漏洞名称
                                            Sec_Api.Sec_LoopScan_Service_Api.Looppayload.Append(base1 + "\r\n");//有效载荷
                                            Sec_Api.Sec_LoopScan_Service_Api.Loopkeyword.Append(base2 + "\r\n");//漏洞关键特征
                                            Sec_Api.Sec_LoopScan_Service_Api.Loopaddr.Append(loopaddr + "\r\n");//漏洞复测地址
                                            Sec_Api.Sec_LoopScan_Service_Api.Looptype.Append(looptype + "\r\n");//漏洞类型
                                            Sec_Api.Sec_LoopScan_Service_Api.Looplevel.Append(looplevel + "\r\n");//漏洞等级
                                            Sec_Api.Sec_LoopScan_Service_Api.Loopnumber.Append(loopnumber + "\r\n");//漏洞编号
                                            Sec_Api.Sec_LoopScan_Service_Api.Cnvd.Append(cnvd + "\r\n");//cnvd编号
                                            Sec_Api.Sec_LoopScan_Service_Api.Cnnvd.Append(cnnvd + "\r\n");//cnnvd编号
                                            Sec_Api.Sec_LoopScan_Service_Api.Cve.Append(cve + "\r\n");//cve编号
                                            Sec_Api.Sec_LoopScan_Service_Api.Revise.Append(revise + "\r\n");//修复建议
                                            Sec_Api.Sec_LoopScan_Service_Api.Accuracy.Append(accuracy + "\r\n");//漏洞准确率
                                            Sec_Api.Sec_LoopScan_Service_Api.Addtime.Append(addtime + "\r\n");//添加时间
                                            Sec_Api.Sec_LoopScan_Service_Api.UrlBase.Append(url + base1 + "\r\n");//把url地址与有效载荷进行输出
                                            Console.WriteLine("存在规则内不报错的情况下：" + DateTime.Now);
                                        }
                                    }
                                }
                            }
                            catch(Exception ex)
                            {
                                //httpweb请求类的报错
                                string Exp = ex.ToString();
                                Sec_Api.Sec_LoopScan_Service_Api.OptionsExp = Exp.ToString();
                                Sec_Api.Sec_LoopScan_Service_Api.Id.Append(id + "\r\n");//漏洞主键编号
                                Sec_Api.Sec_LoopScan_Service_Api.Loopname.Append(loopname + "\r\n");//传出漏洞名称
                                Sec_Api.Sec_LoopScan_Service_Api.Looppayload.Append(base1 + "\r\n");//有效载荷
                                Sec_Api.Sec_LoopScan_Service_Api.Loopkeyword.Append(base2 + "\r\n");//漏洞关键特征
                                Sec_Api.Sec_LoopScan_Service_Api.Loopaddr.Append(loopaddr + "\r\n");//漏洞复测地址
                                Sec_Api.Sec_LoopScan_Service_Api.Looptype.Append(looptype + "\r\n");//漏洞类型
                                Sec_Api.Sec_LoopScan_Service_Api.Looplevel.Append(looplevel + "\r\n");//漏洞等级
                                Sec_Api.Sec_LoopScan_Service_Api.Loopnumber.Append(loopnumber + "\r\n");//漏洞编号
                                Sec_Api.Sec_LoopScan_Service_Api.Cnvd.Append(cnvd + "\r\n");//cnvd编号
                                Sec_Api.Sec_LoopScan_Service_Api.Cnnvd.Append(cnnvd + "\r\n");//cnnvd编号
                                Sec_Api.Sec_LoopScan_Service_Api.Cve.Append(cve + "\r\n");//cve编号
                                Sec_Api.Sec_LoopScan_Service_Api.Revise.Append(revise + "\r\n");//修复建议
                                Sec_Api.Sec_LoopScan_Service_Api.Accuracy.Append(accuracy + "\r\n");//漏洞准确率
                                Sec_Api.Sec_LoopScan_Service_Api.Addtime.Append(addtime + "\r\n");//添加时间
                                Sec_Api.Sec_LoopScan_Service_Api.UrlBase.Append(url + base1 + "\r\n");//把url地址与有效载荷进行输出
                                Console.WriteLine(Exp);
                            }
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                //数据库的请求报错
                string Exp = ex.ToString();
                Sec_Api.Sec_LoopScan_Service_Api.OptionsExp = Exp.ToString();
            }
            return loop;
        }
    }
}
